#include "ODR.h" 
#include "globals.h"

struct sockaddr *GetMacFromFd (int sockfd); 
void free_hwa_info(struct hwa_info *hwahead);
char* printMacAddress(struct sockaddr* sockaddr);

message reqmessage;
char interface[5];
char canonicalip[IPSIZE];
int odr_broadcastid;

int main(int argc, char **argv) {
	
	printf("\nAssignment #3 - ODR Process\n");
	printf("Group 16 - Raghupathy Sekar, Raman Nanda, Supriya Vasudevan\n");
	if (argc != 2)
		err_quit("Usage: ODR <Staleness Time> \n");
	
	stalenessTime = atoi(argv[1]);
	if (stalenessTime == 0)
		err_quit("Error: Staleness Paramater Incorrect!\n");
	
	printf("\tStaleness Time (Sec) Parameter: %d\n\n", stalenessTime);
	
	routingTableHead.next = NULL;
	
	obtainInterfaceInformation();
	createPFPacketSocket();
	createDomainSocket();
	monitorSockets();
}


int obtainInterfaceInformation() {
	printf("(-) Attempting to Obtain Interface Information...\n");
	struct hwa_info *hwahead;
	struct sockaddr *sa;
	char *ptr;
	int i, prflag;
	
	/** Code Adjusted From "get_hw_addrs.c" **/
	for (hwahead = hwaInfo = Get_hw_addrs(); hwaInfo != NULL; hwaInfo = hwaInfo->hwa_next) {
		printf("Interface: %s ", hwaInfo->if_name);
		strncpy(interface, hwaInfo->if_name, sizeof(hwaInfo->if_name));
		//interface[4] = '\0';
		if((hwaInfo->ip_alias) == IP_ALIAS) {
			printf("(Alias)\n");
		} else {
			printf("\n");
		}
	
		if((sa = hwaInfo->ip_addr) != NULL)
			printf("\tIP Address: %s\n", Sock_ntop_host(sa, sizeof(*sa)));
		if (strcmp(interface, "eth0\0") == 0) {
            	strncpy(canonicalip, Sock_ntop_host(sa, sizeof(*sa)), IPSIZE);
            	printf("Here\n");
		}
		prflag = 0;
		i = 0;
		do {
			if (hwaInfo->if_haddr[i] != '\0') {
				prflag = 1;
				break;
			}
		} while (++i < IF_HADDR);

		if (prflag) {
			printf("\tHW Address: ");
			ptr = hwaInfo->if_haddr;
			i = IF_HADDR;
			do {
				printf("%.2x%s", *ptr++ & 0xff, (i == 1) ? " " : ":");
			} while (--i > 0);
			printf("\n");
		} else {
			// No Hardware Address	
			int sockfd;
			sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
			if(sockfd < 0) {
				printf("\nError Creating Sock FD!\n");
				// TODO
			} else {
				struct ifreq ifr;
				ifr.ifr_addr.sa_family = AF_INET;
				strncpy(ifr.ifr_name, hwaInfo->if_name, IFNAMSIZ-1);
				if((Ioctl(sockfd, SIOCGIFHWADDR, &ifr)) == 0) {
					unsigned char* mac;
					mac = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
					printf("\tHW Address: %02x:%02x:%02x:%02x:%02x:%02x\n",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); 
				} else {
					printf("\n%d\n", errno);
				}
				Close(sockfd);
			}
		}
		printf("\tInterface Index: %d\n\n", hwaInfo->if_index);	
	}
	free_hwa_info(hwahead);
	
	return 1;
}

int createPFPacketSocket() {
	// Go Through the Interfaces Again... Create and Bind Sockets
	printf("(-) Attempting to Create PF_Packet Sockets...\n");
	struct hwa_info *hwahead;
	struct sockaddr *sa;
	int socketCount = 0;
	
	int socketDiscript[50];
	int interfaceIndex[50];
	char *networkInterface[50];
	struct sockaddr *hardwareAddress[50];
	
	for (hwahead = hwaInfo = Get_hw_addrs(); hwaInfo != NULL; hwaInfo = hwaInfo->hwa_next) {
		if(strcmp(hwaInfo->if_name, "lo") != 0 && strcmp(hwaInfo->if_name, "eth0") != 0) {
			printf("\tCreating PF_Packet Socket for Interface: %s \n", hwaInfo->if_name);
			int sockfd;
			sockfd = Socket(PF_PACKET, SOCK_RAW, htons(PROTOCOL_VAL));
			if (sockfd < 0) {
				err_quit("\nError: Could Not Create PF_Packet Socket!\n");
			} else {
				printf("\t\tCreated SockFD: %d\n", sockfd);
				int bindResult;
				//struct ifreq ifr;
				//memset(&ifr, 0, sizeof(ifr)); 
				//strncpy(ifr.ifr_ifrn.ifrn_name, hwaInfo->if_name, IFNAMSIZ);
				
				//struct sockaddr_ll inside_address;
				//memset(&inside_address, 0, sizeof(inside_address));
        		//inside_address.sll_family = PF_PACKET;
        		//inside_address.sll_protocol = htons(ETH_P_ALL);
				//inside_address.sll_ifindex = hwaInfo->if_index;
        		//inside_address.sll_hatype = ARPHRD_ETHER;
        		//inside_address.sll_pkttype = PACKET_OTHERHOST;
        		//inside_address.sll_halen = ETH_ALEN;
				
				struct sockaddr_ll inside_address;
				struct ifreq ifr;
				
				bzero(&inside_address, sizeof(inside_address));
				bzero(&ifr, sizeof(ifr));
				
				strncpy((char *)ifr.ifr_name, hwaInfo->if_name, IFNAMSIZ);
				inside_address.sll_family = PF_PACKET;
				inside_address.sll_ifindex = hwaInfo->if_index;
				inside_address.sll_protocol = htons(PROTOCOL_VAL);
				
				bindResult = bind(sockfd, (struct sockaddr *) &inside_address, sizeof(inside_address));
				
				if(bindResult < 0) {
					Close(sockfd);
					err_quit("\nError: Could Bind PF_Packet Socket!\n");
				}
				else {
					printf("\t\tBinded Socket to Interface!\n");
					
					struct ifreq ifr;
					ifr.ifr_addr.sa_family = AF_INET;
					strncpy(ifr.ifr_name, hwaInfo->if_name, IFNAMSIZ-1);
					if((Ioctl(sockfd, SIOCGIFHWADDR, &ifr)) == 0) {
						unsigned char* mac;
						mac = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
						socketDiscript[socketCount] = sockfd;
						interfaceIndex[socketCount] = hwaInfo->if_index;
						networkInterface[socketCount] = Malloc(sizeof(char[IFNAMSIZ]) + 1);
						strncpy(networkInterface[socketCount], hwaInfo->if_name, sizeof(char[IFNAMSIZ]));
						hardwareAddress[socketCount] = Malloc(sizeof(ifr.ifr_hwaddr) + 1);
						memcpy(hardwareAddress[socketCount],&ifr.ifr_hwaddr, sizeof(struct sockaddr) );
			//			printf("mac %02x: %02x\n", hardwareAddress[socketCount]->sa_data[0], hardwareAddress[socketCount]->sa_data[1]);
						//strncpy(hardwareAddress[socketCount], mac, sizeof(ifr.ifr_hwaddr.sa_data));	
					}
				}
			}
			socketCount++;
		}	
	}
	
	pfSocketInfo.sockfd = malloc(socketCount*sizeof(int));
	pfSocketInfo.interfaceIndex = malloc(socketCount*sizeof(int));
	pfSocketInfo.interfaceName = malloc(socketCount * sizeof *pfSocketInfo.interfaceName);
	pfSocketInfo.hardwareAddress = malloc(socketCount * sizeof *pfSocketInfo.hardwareAddress);
	
	if(socketCount == 0) {
		err_quit("\nError: Could Not Create PF_Packet Sockets! No Interfaces!\n");
	} else {
		int i;
		for (i = 0; i < socketCount; i++) {
			pfSocketInfo.sockfd[i] = socketDiscript[i];
			pfSocketInfo.interfaceName[i] = networkInterface[i];
			pfSocketInfo.interfaceIndex[i] = interfaceIndex[i];
			pfSocketInfo.hardwareAddress[i] = hardwareAddress[i];
		}
		pfSocketInfo.socketCount = socketCount;
	}
}

int createDomainSocket() {
	printf("\n(-) Attempting to Create Domain Socket...\n");
	/** Taken From: http://beej.us/guide/bgipc/output/html/multipage/unixsock.html */
	int sockfd, len, bindResult;
	sockfd = Socket(AF_LOCAL, SOCK_DGRAM, 0);
	if(sockfd < 0) {
		err_quit("Could Not Create Domain Socket!");
	}
	printf("\tCreated Domain Socket on SockFD: %d\n", sockfd);
	
	struct sockaddr_un local;
	unlink(CUSTOM_SUN_PATH);
	bzero(&local, sizeof(local));
	local.sun_family = AF_LOCAL;
	strcpy(local.sun_path, CUSTOM_SUN_PATH);
	
	bindResult = bind(sockfd, (struct sockaddr *) &local, sizeof(local));
	if(bindResult < 0) {
		err_quit("\nCould Not Bind Domain Socket!\n");
	}
	printf("\t\tBinded Socket to Interface!\n");
	domainSocketInfo.sockfd = sockfd;
}

int buildInitalRoutingTable() {
	// Nothing should be here - Table was Build in the Header;
}

int updateRoutingTable() {

}

int monitorSockets() {
	fd_set rset;
	FD_ZERO(&rset);
	int maxfd, nready, i, j;
	maxfd = 0;
	rreq_id_list *id_head = (rreq_id_list *)Malloc(sizeof(rreq_id_list));
	id_head->next = NULL;
	
	printf("\n(-) Monitoring Sockets for Incomming Connections\n");

	for( ; ; ) {	
		
		// Add the Packet Socket Monitoring
		maxfd = domainSocketInfo.sockfd;
		for(i = 0; i < pfSocketInfo.socketCount; i++) {
			maxfd = max(maxfd, pfSocketInfo.sockfd[i]);
		}
	
		for(i = 0; i < pfSocketInfo.socketCount; i++) {
			int fd = pfSocketInfo.sockfd[i];
			FD_SET(fd, &rset);
		}
		// Add the Domain Socket Monitoring
		FD_SET(domainSocketInfo.sockfd, &rset);
		
		if((nready = Select(maxfd + 1, &rset, NULL, NULL, NULL)) < 0) {
			if(errno == EINTR) {
				continue;
			}	
			else
				err_quit("Select Error!");				   
		} 

		if(FD_ISSET(domainSocketInfo.sockfd, &rset)) {
			monitorDomainSocket(domainSocketInfo.sockfd, id_head); 
		}
		for(j = 0; j < pfSocketInfo.socketCount; j++) {
			int sockfd = pfSocketInfo.sockfd[j];
			if(FD_ISSET(sockfd, &rset)) {
				if (monitorPacketSocket(sockfd, id_head) == 0) {
					printf("Reached home");	
					exit(EXIT_SUCCESS);
				}
			}
		}
	}
}

int monitorDomainSocket(int sockfd, rreq_id_list *id_head) {

	struct sockaddr_un sockaddr;
	//struct msg_recv_struct mesg;
  	odr_request *odr_req = (odr_request *)Malloc(sizeof(odr_request));;
	int len;
	int n;
//	rreqid *rreqid_new = (rreqid *)Malloc(sizeof(rreqid));
	bzero(&sockaddr, sizeof(sockaddr));
	sockaddr.sun_family = AF_LOCAL;
	strcpy(sockaddr.sun_path, CUSTOM_SUN_PATH);
	len = sizeof(struct sockaddr);
	printf("Sockfd: %d\n", sockfd);
	
	n = Recvfrom(sockfd, &reqmessage, sizeof(reqmessage), 0, NULL, NULL);
	if(n > 0) {
		printf("new request from client\n");
//		odr_req->odr_req_recv.broadcastid = odr_broadcastid++;
//		memcpy(&rreqid_new->broadcastid, &odr_req->odr_req_recv.broadcastid, sizeof(int));;		
//		memcpy(rreqid_new->sourceip, canonicalip, IPSIZE);
		
//		insert_id(rreqid_new, id_head);
         printf("1");
		memcpy(&reqmessage.sourceip, &canonicalip, IPSIZE);
		reqmessage.broadcastid = odr_broadcastid++;	
		
     	memcpy(&odr_req->odr_req_recv, &reqmessage, sizeof(message));
		
		printf("2");
		

		printf("3");
		
		printf("broadcastid %d\n", odr_req->odr_req_recv.broadcastid);
		printf("canonical ip %s\n", odr_req->odr_req_recv.sourceip); 
		printf("4");
		
		
		floodRREQ(odr_req, 0, NULL, -1);
	} else {
		printf("Error in ODR domain socket");
	}	
	//memset(msg_recvd, '\0', 50);
	//strncpy(msg_recvd, mesg.msg, 50);/odr
	//memset(src_addr, '\0', 17);
	//strncpy(src_addr, mesg.src_addr, 17);
	//*src_port = mesg.src_port;
	/**
	char* destination;// = src_addr;
	
	int i, destinationFound;
	destinationFound = -1;
	for(i = 0; i < routes.size; i++) {
		if(strcmp(destination, routes.destination[i]) == 0) {
			destinationFound = i;
		}
	}
	
	if(destinationFound == -1) {
		//floodRREQ(destination, 0);
	}
	else {
		// Check Time for Route Staleness
		time_t lastUpdated = routes.timeStamp[destinationFound];
		time_t currentTime = time(NULL);
		double difTime = difftime(currentTime,lastUpdated);
		if(difTime < stalenessTime) {
			// Go about Normal Ways
		} else {
			//floodRREQ(destination, 1);
		}
	}
	**/
}

int monitorPacketSocket(int sockfd, rreq_id_list *id_head) 
{
	int type;
	unsigned char dest_mac[6];
	odr_request *odr_req = (odr_request *)Malloc(sizeof(odr_request));
	void* buffer = (void*)malloc(ETH_FRAME_LEN); /*Buffer for ethernet frame*/
	rreqid *rreqid_new = (rreqid *)Malloc(sizeof(rreqid));
	int length = recvfrom(sockfd, buffer, ETH_FRAME_LEN, 0, NULL, NULL);
	unsigned char* data = buffer + 14;
	
	struct ethhdr *ether_header = (struct ethhdr *)buffer;
	char *src_addr = buffer + 6;
	
	
	struct sockaddr *tempmac;
	struct sockaddr *sourcemac = NULL;
	
	if (length > 0) {
		printf("\tRecieved RAW Socket Data\n");
		memcpy(&type, data, sizeof(int));
		
		if (type == 1) {
		/* RREQ received */
			printf("RREQ is arrived\n");	
			memcpy(odr_req, data, sizeof(odr_request));
			tempmac = GetMacFromFd(sockfd); 
			printf("before memcpy of mac\n");
			sourcemac = tempmac;
			printf("source mac %s\n", printMacAddress(sourcemac));
			if(strcmp(canonicalip, odr_req->odr_req_recv.destip) != 0) {
				/* Check if request is already received */
				printf("broadcastid %d\n", odr_req->odr_req_recv.broadcastid);
				if (find_id(odr_req->odr_req_recv.broadcastid, odr_req->odr_req_recv.sourceip,id_head) == 0) {
					printf("Broadcastid already received\n"); 
					return 0; 
				} else {
					printf("new request\n");
					rreqid_new->broadcastid = odr_req->odr_req_recv.broadcastid;		
					memcpy(rreqid_new->sourceip, odr_req->odr_req_recv.sourceip, IPSIZE);
					printf("source ip inside rreq %s\n", rreqid_new->sourceip);
					
      				
					routingtable_data *tempData = (routingtable_data *)find_route(&routingTableHead, rreqid_new->sourceip);
					if(tempData == NULL) {
 		                 	
						routingtable_data *newRoute = (routingtable_data*) Malloc(sizeof(routingtable_data));
 		                 	
						strncpy(newRoute->destination, odr_req->odr_req_recv.sourceip, IPSIZE);
 		                 	
						printf("\t Src %02x: %02x: %02x: %02x: %02x: %02x\n", src_addr[0], src_addr[1], src_addr[2], src_addr[3], src_addr[4], src_addr[5]);
 		                 	
 		                 	
						memcpy(&newRoute->nextHop, src_addr, ETH_ALEN);
 		                 	
						newRoute->outgoingInterfaceIndex = getInterfaceFromFd(sockfd);
 
						printf("Hop Count %d",  odr_req->hopcount);
	
						
						
 		                 	
						time_t currentTime = time(NULL);
 		                 	
						memcpy(&newRoute->timeStamp, &currentTime, sizeof(time_t));
 		                 	
 		                 	
 		                 	
						printf("New Entry in the Routing Table\n");
 		                 	
						printf("\t Destination: %s\n", newRoute->destination);
 	
 		                 	
						printf("\t Next Hop %02x: %02x: %02x: %02x: %02x: %02x\n", newRoute->nextHop[0], newRoute->nextHop[1], newRoute->nextHop[2], newRoute->nextHop[3], newRoute->nextHop[4], newRoute->nextHop[5]);
 		                 	
						printf("\t Outgoing Interface: %d\n", newRoute->outgoingInterfaceIndex);
 		                 	
 		                 	
 		                 	//TODO:
 		                 	int *hops = (int *)newRoute->numberOfHops;
						printf("\t Num Hops: %d\n", hops);
 		                 	
						struct tm *local;
 		                 	
						local = localtime(&newRoute->timeStamp);
 		                 	
						printf("\t TimeStamp: %s\n", asctime(local));
 		                 	
     					
						add_route(&routingTableHead, newRoute);
                        
					}					
					
					
					
					
					printf("broadcast id inserted in list %d\n", rreqid_new->broadcastid);
					insert_id(rreqid_new, id_head);	
                        
					//unsigned char dest_mac[6] = {0x00, 0x0c, 0x29, 0x5a, 0x36, 0x92};
					//memcpy(sourcemac->sa_data, dest_mac, 6);
					floodRREQ(odr_req, 0, NULL, sockfd);
					return 1;
				}
			} else {
				printf("Reached IP address %s\n", odr_req->odr_req_recv.destip);
				return 0;
			}
		} else if (type == 2) {
		/* RREP received */
			printf("RREP is received");	
		}
	}
}

int floodRREQ(odr_request *odr_req, int forcedDiscovery, struct sockaddr *sourceaddr, int inIndex) 
{
	int i;
	// Flood Message over all Interfaces...
	for(i = 0; i < pfSocketInfo.socketCount; i++) {
       
		if(inIndex == -1) {
           odr_req->hopcount = 0;
          struct sockaddr *tempSock = GetMacFromFd(pfSocketInfo.sockfd[i]);
           	printf("Print Sock Addr %s\n", printMacAddress(tempSock));
      		memcpy(&odr_req->odr_req_recv.sourcemac, tempSock->sa_data, ETH_ALEN);
       	}
		if(inIndex != pfSocketInfo.sockfd[i])
      		generateRREQ(pfSocketInfo.sockfd[i], odr_req, pfSocketInfo.hardwareAddress[i], pfSocketInfo.interfaceIndex[i], forcedDiscovery, sourceaddr);
	}
}

int generateRREQ(int sockfd, odr_request *odr_req, struct sockaddr *hardwareAddress, int hardwareIndex, int forcedDiscovery, struct sockaddr *destaddr) {
	struct sockaddr_ll srcaddr, dstaddr;
	socklen_t len;
	struct ethhdr ether_header;
	char* msg;
	if((msg = malloc(ETH_FRAME_LEN)) == NULL) {
      printf("Error\n");
      return -1;
    }
	
	//TODO Update
	odr_request *request_struct = (odr_request *) (msg + sizeof(struct ethhdr));
	
	char hw_source_addr[ETH_ALEN];
	memcpy(hw_source_addr, hardwareAddress->sa_data, ETH_ALEN);
	
	char hw_dest_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
	if (destaddr != NULL) {	
		printf("Unicasting !!!!!!!!!!!!!\n");
		memcpy(hw_dest_addr, destaddr->sa_data, ETH_ALEN);
	}
	else {
		printf("Multicasting !!!!!!!!!!!\n");
	}
	
	
	int i, j;
	int msg_size;
	
	printf("Packet Source MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", hw_source_addr[0], hw_source_addr[1], hw_source_addr[2], hw_source_addr[3], hw_source_addr[4], hw_source_addr[5]); /** Messed uP **/
	printf("Packet Destination MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", hw_dest_addr[0], hw_dest_addr[1], hw_dest_addr[2], hw_dest_addr[3], hw_dest_addr[4], hw_dest_addr[5]);
     
    len = sizeof(struct sockaddr_ll);
    dstaddr.sll_protocol = htons(PROTOCOL_VAL);
    dstaddr.sll_ifindex = hardwareIndex; /* interface "eth0" */
    memcpy (dstaddr.sll_addr, hw_dest_addr, ETH_ALEN); 
    memcpy (srcaddr.sll_addr, hw_source_addr, ETH_ALEN); 
    memcpy (ether_header.h_dest, hw_dest_addr, ETH_ALEN);
    memcpy (ether_header.h_source, srcaddr.sll_addr, ETH_ALEN);  
    
    printf("Header Source MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", ether_header.h_source[0], ether_header.h_source[1], ether_header.h_source[2], ether_header.h_source[3], ether_header.h_source[4], ether_header.h_source[5]);
    printf("Header Destination MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", ether_header.h_dest[0], ether_header.h_dest[1], ether_header.h_dest[2], ether_header.h_dest[3], ether_header.h_dest[4], ether_header.h_dest[5]);
  
    ether_header.h_proto = htons(PROTOCOL_VAL); 
    odr_req->type = 1;	
    
    int hopCount = odr_req->hopcount;
    hopCount += 1;
    
    //odr_req.hopcount = hopCount;
    memcpy(&odr_req->hopcount, &hopCount, sizeof(int));
    memcpy(request_struct, odr_req, sizeof(odr_request));
    
    msg_size = ETH_FRAME_LEN; 
    
    //bzero(&msg, sizeof(msg));
    memcpy (msg, &ether_header, sizeof(ether_header)); 
    for (j = 0; j < msg_size; j++) { 
      //printf ("0x%2.2X ", msg[j] & 0x000000FF); 
    } 
    printf ("\n\n");
	
	int send_result = sendto(sockfd, msg, msg_size, 0,(struct sockaddr*)&dstaddr, len);
	if (send_result == -1) {
		printf("Failure: Could Not Sent RREQ on Interface Index: %d\n", hardwareIndex);
	} else {
		printf("\tSent RREQ on Interface Index: %d! - Code: %d\n", hardwareIndex, send_result); 
	}
}
 
int generateRREP() {
//TODO

printf("RREP generate plzzzzzzzzzzz");
}

struct hwa_info* get_hw_addrs()
{
	struct hwa_info	*hwa, *hwahead, **hwapnext;
	int		sockfd, len, lastlen, alias;
	char		*ptr, *buf, lastname[IF_NAME], *cptr;
	struct ifconf	ifc;
	struct ifreq	*ifr, ifrcopy;
	struct sockaddr	*sinptr;

	sockfd = Socket(AF_INET, SOCK_DGRAM, 0);

	lastlen = 0;
	len = 100 * sizeof(struct ifreq);	/* initial buffer size guess */
	for ( ; ; ) {
		buf = (char*) Malloc(len);
		ifc.ifc_len = len;
		ifc.ifc_buf = buf;
		if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
			if (errno != EINVAL || lastlen != 0)
				err_sys("ioctl error");
		} else {
			if (ifc.ifc_len == lastlen)
				break;		/* success, len has not changed */
			lastlen = ifc.ifc_len;
		}
		len += 10 * sizeof(struct ifreq);	/* increment */
		free(buf);
	}
	hwahead = NULL;
	hwapnext = &hwahead;
	lastname[0] = 0;
	for (ptr = buf; ptr < buf + ifc.ifc_len; ) {
		ifr = (struct ifreq *) ptr;
		len = sizeof(struct sockaddr);
		ptr += sizeof(ifr->ifr_name) + len;	/* for next one in buffer */
		alias = 0; 
		hwa = (struct hwa_info *) Calloc(1, sizeof(struct hwa_info));
		memcpy(hwa->if_name, ifr->ifr_name, IF_NAME);		/* interface name */
		hwa->if_name[IF_NAME-1] = '\0';
				/* start to check if alias address */
		if ( (cptr = (char *) strchr(ifr->ifr_name, ':')) != NULL)
			*cptr = 0;		/* replace colon will null */
		if (strncmp(lastname, ifr->ifr_name, IF_NAME) == 0) {
			alias = IP_ALIAS;
		}
		memcpy(lastname, ifr->ifr_name, IF_NAME);
		ifrcopy = *ifr;
		*hwapnext = hwa;		/* prev points to this new one */
		hwapnext = &hwa->hwa_next;	/* pointer to next one goes here */

		hwa->ip_alias = alias;		/* alias IP address flag: 0 if no; 1 if yes */
                sinptr = &ifr->ifr_addr;
		hwa->ip_addr = (struct sockaddr *) Calloc(1, sizeof(struct sockaddr));
	        memcpy(hwa->ip_addr, sinptr, sizeof(struct sockaddr));	/* IP address */
		Ioctl(sockfd, SIOCGIFHWADDR, &ifrcopy);	/* get hw address */
		memcpy(hwa->if_haddr, ifrcopy.ifr_hwaddr.sa_data, IF_HADDR);
		Ioctl(sockfd, SIOCGIFINDEX, &ifrcopy);	/* get interface index */
		memcpy(&hwa->if_index, &ifrcopy.ifr_ifindex, sizeof(int));
	}
	free(buf);
	return(hwahead);	/* pointer to first structure in linked list */
}


struct hwa_info* Get_hw_addrs()
{
	struct hwa_info	*hwa;
	if ( (hwa = get_hw_addrs()) == NULL)
		err_quit("get_hw_addrs error");
	return(hwa);
}

struct sockaddr *GetMacFromFd (int sockfd) 
{
	int j;
	unsigned char *mac;
	struct sockaddr *temphwaddr;
	for(j = 0; j < pfSocketInfo.socketCount; j++) {
		if(pfSocketInfo.sockfd[j] == sockfd) {
		//	mac = (unsigned char *)&pfSocketInfo.hardwareAddress[j];
			temphwaddr = pfSocketInfo.hardwareAddress[j];
			mac = temphwaddr->sa_data;
			printf("mac %02x: %02x: %02x: %02x: %02x: %02x\n",mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 
			return pfSocketInfo.hardwareAddress[j];
      		}
	}
	printf("Return NULL\n");
	return NULL;
}

int getInterfaceFromFd(int sockfd) {
    int j;
    for(j = 0; j < pfSocketInfo.socketCount; j++) {
        if(pfSocketInfo.sockfd[j] == sockfd) {
            return pfSocketInfo.interfaceIndex[j];
        }
    }
    return -1;
}

void free_hwa_info(struct hwa_info *hwahead)
{
	struct hwa_info	*hwa, *hwanext;
	for (hwa = hwahead; hwa != NULL; hwa = hwanext) {
		free(hwa->ip_addr);
		hwanext = hwa->hwa_next;	/* can't fetch hwa_next after free() */
		free(hwa);			/* the hwa_info{} itself */
	}
}

char* printMacAddress(struct sockaddr* sockaddr) {
	unsigned char *mac;
	printf("here 1");
	mac = sockaddr->sa_data;
	char *buffer = (char *)Malloc(50);
	sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
	return buffer;
}
